Discovering features using HTTP OPTIONS
使用 HTTP OPTIONS 发现功能
Say you have an API, and you want to communicate what sort of things a user can
do on a specific endpoint. You can use external description formats like OpenAPI
or JSON Schema, but sometimes it’s nice to also dynamically communicate this on
the API itself.
假设你有一个 API,并且你想传达用户可以在特定端点上执行哪些作。您可以使用外部描述格式,例如 OpenAPI 或 JSON Schema,但有时也最好在 API 本身上动态传达这一点。
OPTIONS
is the method used for that. You may know this HTTP method from
CORS, but it’s general purpose is for clients to passively find out ‘What
can I do here?’.OPTIONS
是用于此目的的方法。您可能知道这个 HTTP 方法
CORS,但它的一般目的是让客户被动地发现“我能在这里做什么?
All HTTP clients typically support making OPTIONS
request. For example with
fetch()
:
所有 HTTP 客户端通常都支持发出 OPTIONS
请求。例如,使用
fetch()
:
const response = await fetch(
'https://example.org',
{method: 'OPTIONS'}
);
A basic OPTIONS
response might might look like this:
基本的 OPTIONS
响应可能如下所示:
HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 02:57:38 GMT
Server: KKachel/1.2
Allow: GET, PUT, POST, DELETE, OPTIONS
Based on the Allow
header you can quickly tell which HTTP methods
are available at a given endpoint. Many web frameworks emit this automatically
and generate the list of methods dynamically per route, so chances are that you
get this one for free.
根据 Allow
标头,您可以快速判断给定端点上有哪些 HTTP 方法可用。许多 Web 框架会自动发出此信息,并按路由动态生成方法列表,因此您很可能会免费获得此方法。
To find out if your server does, try running the command below (with your
URL!):
要了解您的服务器是否这样做,请尝试运行以下命令(使用您的 URL!
curl -X OPTIONS http://localhost:3000/some/endpoint/
One nice thing you could do with the Allow
header, is that you could also
communicate access-control information on a very basic level. For example,
you could only include DELETE
and PUT
if a user has write access to
a resource.
您可以使用 Allow
标头做的一件好事是,您还可以在非常基本的级别上传达访问控制信息。例如,如果用户对资源具有写入访问权限,则只能包含 DELETE
和 PUT
。
Accept and Accept-Encoding
接受和接受编码
There’s server other standard headers for discovery. Here’s an example showing
a few at once:
还有服务器其他标准标头可供发现。下面是一个示例,一次显示几个:
HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 02:57:38 GMT
Server: KKachel/1.2
Allow: GET, PUT, POST, DELETE, OPTIONS
Accept: application/vnd.my-company-api+json, application/json, text/html
Accept-Encoding: gzip,brotli,identity
You may already be familiar with Accept
and Accept-Encoding
from
HTTP requests, but they can also appear in responses. Accept
in a response
lets you tell the client which kind of mimetypes are available at an endpoint.
I like adding text/html
to every JSON api endpoint and making sure that
API urls can be opened in browsers and shared between devs for easy debugging.
您可能已经熟悉 HTTP 请求中的 Accept
和 Accept-Encoding
,但它们也可能出现在响应中。Accept
in a response 允许您告诉客户端端点上可用的 mimetype 类型。我喜欢将 text/html
添加到每个 JSON API 端点,并确保 API URL 可以在浏览器中打开并在开发人员之间共享,以便于调试。
The Accept-Encoding
lets a client know in this case that they can compress
their request bodies with either gzip
or brotli
(identity
means no
compression).
在这种情况下,Accept-Encoding
让客户端知道他们可以使用 gzip
或 brotli
压缩他们的请求正文( 身份
意味着不压缩)。
Patching, posting and querying
修补、发布和查询
3 other headers that can be used are Accept-Patch
, Accept-Post
and Accept-Query
. These three headers are used to tell a client what
content-types are available for the PATCH
, POST
and
QUERY
http methods respectively.
其他 3 个可以使用的标头是 Accept-Patch
、Accept-Post
和 Accept-Query 的 Accept-Query
中。这三个标头用于告诉客户端哪些内容类型可用于 PATCH、
POST
和
QUERY
http 方法。
For all of these headers, their values effectively dictate what valid
values are for the Content-Type
header when making the request.
对于所有这些标头,它们的值有效地规定了发出请求时 Content-Type
标头的有效值。
HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 02:57:38 GMT
Server: KKachel/1.2
Allow: OPTIONS, QUERY, POST, PATCH
Accept-Patch: application/json-patch+json, application/merge-patch+json
Accept-Query: application/graphql
Accept-Post: multipart/form-data, application/vnd.custom.rpc+json
In the above response, the server indicates it supports both JSON Patch
and JSON Merge Patch content-types in PATCH
requests. It also suggests
that GraphQL can be used via the QUERY
method, and for POST
it supports
both standard file uploads and some custom JSON-based format.
在上述响应中,服务器表示它支持 JSON 补丁
以及 JSON 合并补丁 PATCH
请求中的内容类型。它还建议可以通过 QUERY
方法使用 GraphQL,对于 POST
,它支持标准文件上传和一些基于 JSON 的自定义格式。
Typically you wouldn’t find all of these at the same endpoint, but I wanted
to show a few examples together.
通常,您不会在同一端点找到所有这些,但我想一起展示几个示例。
Where’s PUT? 看跌期权在哪里?
Oddly, there’s no specific header for PUT
requests. Arguably you could say
that GET
and PUT
are symmetrical, so perhaps the Accept
header kind of
extends to both. But the spec is not clear on this.
奇怪的是,PUT
请求没有特定的标头。可以说, 您可以说 GET
和 PUT
是对称的,所以也许 Accept
标头可以扩展到两者。但规范对此并不清楚。
I think the actual reality is that Accept-Patch
was the first header in
this category that really clearly defined this as a means of feature discovery
on OPTIONS
. Accept-Post
and Accept-Query
followed suit. I think
Accept-Patch
in OPTIONS
was modelled after in-the-wild usage of Accept
in OPTIONS
, even though the HTTP specific doesn’t super clearly define this.
我认为实际的现实是,Accept-Patch
是该类别中第一个真正明确地将其定义为 OPTIONS
上功能发现手段的标头。Accept-Post
和 Accept-Query
紧随其后。 我认为
OPTIONS
中的 Accept-Patch
是在 Accept
的野外用法之后建模的
在 OPTIONS
中,即使 HTTP 特定并没有非常清楚地定义这一点。
If I’m wrong with my interpretation here, I would love to know!
如果我在这里的解释有误,我很想知道!
Aside: If you’re wondering about DELETE
, DELETE
should never have a body,
so all a user would need to know is can they delete, which you can see
in the Allow
header.
If this is new to you to, read my other article about GET
request
bodies. Most of the information there is applicable to DELETE
as well.
题外话:如果您想知道 DELETE,DELETE
永远不应该有正文 ,因此用户需要知道的只是他们是否可以删除,您可以在
Allow
标头中看到。如果这对您来说是新的, 请阅读我关于 GET
请求正文的另一篇文章。那里的大多数信息也适用于 DELETE
。
Linking to documentation
链接到文档
The OPTIONS
response is also a great place to tell users where to find
additional documentation. In the below example, I included both a
machine-readable link to a documentation site, a link to an OpenAPI definition,
and a message intended for humans in the response body:OPTIONS
响应也是告诉用户在哪里可以找到其他文档的好地方。在下面的示例中,我在响应正文中包含了一个指向文档站点的机器可读链接、一个指向 OpenAPI 定义的链接以及一条面向人类的消息:
HTTP/1.1 200 OK
Date: Mon, 23 Sep 2024 04:45:38 GMT
Allow: GET, QUERY, OPTIONS
Link: <https://docs.example.org/api/some-endpoint>; rel="service-doc"
Link: <https://api.example.org/openapi.yml>; rel="service-desc" type="application/openapi+yaml"
Content-Type: text/plain
Hey there!
Thanks for checking out this API. You can find the docs for this
specific endpoint at: https://docs.example.org/api/some-endpoint
Cheers,
The dev team
I recommend keeping the response body as mostly informal and minimal
any real information should probably just live on its own URL and be linked to.
我建议将响应正文保持为大部分非正式和最少,任何真实信息可能都应该存在于它自己的 URL 上并被链接到。
I used the service-doc
and service-desc
link relationships here,
but you can of course use any of the IANA link relationship types here
or a custom one. Also see the Web linking spec for more info.
我在这里使用了 service-doc
和 service-desc
链接关系,但您当然可以在此处使用任何 IANA 链接关系类型或自定义关系类型。另请参阅 Web 链接规范以获取更多信息。
Obscure uses 晦涩难懂的用途
WebDAV usage WebDAV 使用
WebDAV, CalDAV and CardDAV also use OPTIONS for feature discovery. For example:
WebDAV、CalDAV 和 CardDAV 也使用 OPTIONS 进行特征发现。 例如:
HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 05:01:50 GMT
Allow: GET, PROPFIND, ACL, PROPPATCH, MKCOL, LOCK, UNLOCK
DAV: 1, 2, 3, access-control, addressbook, calendar-access
The server-wide asterisk request
服务器范围的星号请求
Normally HTTP requests are made to a path on the server, and the first line
looks a bit like the following in HTTP/1.1:
通常,HTTP 请求是向服务器上的路径发出的,第一行看起来有点像 HTTP/1.1 中的以下内容:
GET /path HTTP/1.1
But, there are a few other “request line” formats that are rarely used. One of
them lets you discover features available on an entire server, using the
asterisk:
但是,还有一些其他很少使用的“请求行”格式。其中一种允许您使用星号发现整个服务器上可用的功能:
OPTIONS * HTTP/1.1
The asterisk here is not a path. Normally asterisks aren’t even allowed in
URIs. Many HTTP clients (including fetch()
) don’t even support this request.
这里的星号不是路径。通常,URI 中甚至不允许使用星号。许多 HTTP 客户端(包括 fetch()
)甚至不支持此请求。
Classic webservers like Apache and Nginx should support this. To try it out,
use CURL
Apache 和 Nginx 等经典 Web 服务器应该支持此功能。要尝试一下,请使用 CURL
curl -vX OPTIONS --request-target '*' http://example.org
Final notes 最后的注意事项
If you have a reason to allow clients to discover features on an endpoint,
consider using OPTIONS
instead of a proprietary approach! As you can
see in many of these examples, it’s especially useful if you use mimetypes
well.
如果您有理由允许客户端发现端点上的功能,请考虑使用 OPTIONS
而不是专有方法!正如您在许多示例中看到的那样,如果您使用 mimetype,它特别有用
井。
If you have questions, other novel uses of OPTIONS
or other ideas around
feature discovery, you can respond via:
如果您有疑问、OPTIONS
的其他新颖用途或有关特征发现的其他想法,您可以通过以下方式回复:
- This post on Mastodon
这篇关于乳齿象的帖子 - This post on Bluesky
这篇文章在蓝天上 - Via the Webmention protocol!
通过 Webmention 协议!
logical skeleton business •
haha i'm planning to use OPTIONS * for the handler manifest protocol in intertwingler逻辑骨架业务 •
哈哈,我计划在 intertwingler 中使用 OPTIONS * 作为处理程序清单协议